package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hmdp.dto.Result;
import com.hmdp.dto.ScrollResult;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IFollowService;
import com.hmdp.utils.UserHolder;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hmdp.utils.RedisConstants.BLOG_LIKED_KEY;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {

    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //stringRedisTemplate.opsForZSet().score(key, userId.toString());
    @Override
    public Result queryBlogById(Long id) {
        /**
         * 查询：1. 回显点赞数量
         *
         *          1.1查找blog用户id
         *    2。我是否点过赞
         *      redis
         *   3。 点赞排行榜
         *      redis：
         *      key ： islike：blogid
         *      value : userId
         *      score : 时间戳，从早到晚排序
         *   4 。 根据redis的score截取排行榜，再通过sql去有序地从数据库查user
         *   5.回显user
         */
        /**
         * getById(id)
         */
        Blog blog = getById(id);
        if (blog == null) {
            return Result.fail("文章不存在");
        }
        //设置blog回显的用户信息，name，icon
        queryBlogUser(blog);
        isBlogLike(blog);
        return Result.ok(blog);

    }

    private void isBlogLike(Blog blog) {
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            // 用户未登录，无需查询是否点赞
            return;
        }
        Long userid = user.getId();
        String key = BLOG_LIKED_KEY + blog.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, String.valueOf(userid));
            blog.setIsLike(score != null);
    }

    private void queryBlogUser(Blog blog) {
        Long userId = blog.getUserId();
        User blogUser = userService.getById(userId);
        blog.setName(blogUser.getNickName());
        blog.setIcon(blogUser.getIcon());
    }

    /**
     * key:  BLOG_LIKED_KEY
     *
     * @param id
     * @return
     */
    @Override
    public Result likeBlog(Long id) {
        UserDTO user = UserHolder.getUser();
        String key = BLOG_LIKED_KEY + user.getId();
        Double score = stringRedisTemplate.opsForZSet().score(key, String.valueOf(user.getId()));
        if (score == null) {
            long time = System.currentTimeMillis();
            boolean isSuccess = update().setSql("liked = liked +1 ").eq("id", id).update();
            if (isSuccess) {
                //可以添加
                stringRedisTemplate.opsForZSet().add(BLOG_LIKED_KEY + id, String.valueOf(user.getId()), time);
            }
        } else {
            boolean isSuccess = update().setSql(" liked = liked -1 ").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(BLOG_LIKED_KEY + id, String.valueOf(user.getId()));
            }
        }
        return Result.ok();
    }

    @Override
    public Result queryBlogLikes(Long id) {
        //查询 2.解析用户 3 . 查询用户  4 .返回
        String key = BLOG_LIKED_KEY + id;
        Set<String> userId = stringRedisTemplate.opsForZSet().range(key, 0, 4);
        if(userId == null || userId.size() == 0) {
            return Result.ok();
        }
        List<Long> ids = userId.stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());

        String idStr = StrUtil.join(",", ids);

        List<User> id1 = userService.query()
                .in("id", ids)
                .last("order by field (id," + idStr + ")")
                .list();

        List<UserDTO> userDTOS = id1.stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        return Result.ok(userDTOS);
    }




    void  A ( Long id ){
        String key = BLOG_LIKED_KEY +id ;
        Set<String> top5 = stringRedisTemplate.opsForZSet()
                .range(key, 0, 4);
        if(top5 == null || top5.size() == 0) {
            return;
        }
        List<Long> ids = top5.stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());
        String idsStr = StrUtil.join(",", ids);
        List<User> id1 = userService.query().in("id", ids)
                .last("order by field (id " + idsStr + ")")
                .list();
        List<UserDTO> userDTOS = id1.stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        return;


    }
    @Autowired
    private IFollowService followService;
    @Override
    public Result saveBlog(Blog blog) {
        // 获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        // 保存探店博文
        boolean success = save(blog);
        if(success){
            List<Follow> follows = followService.query()
                    .eq("follow_user_id", user.getId())
                    .list();
            for (Follow follow : follows) {
                String  key = "Blog:Follow:User:"  + String.valueOf(follow.getUserId());
                stringRedisTemplate.opsForZSet()
                        .add(key,String.valueOf(user.getId()),System.currentTimeMillis());
            }
        }
        return Result.ok(user.getId());
    }

    @Override
    public Result queryBlogOfFollow(Long max, Integer offset) {
        //获取当前用户，根据key = Blog:Follw：User+ userId
        //获取到blog的id，根据id进行查询
        UserDTO user = UserHolder.getUser();
        String key = "Blog:Follow:User:"  + String.valueOf(user.getId());
        //如果是第一次，那个么  offset ,max - 0   0 max offset  2
        Set<ZSetOperations.TypedTuple<String>> typedTuples
                = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, max, offset, 3);
        if(typedTuples == null || typedTuples.size() == 0) {
            return  Result.ok();
        }
        List<Long> ids = new ArrayList<>();
        long maxd = 0 ;
        Integer offsetd = 0 ;
        for(ZSetOperations.TypedTuple<String> typedTuple : typedTuples){
            Long id = Long.valueOf(typedTuple.getValue());
            ids.add(id);
            Double score = typedTuple.getScore();
            long l = score.longValue();
            if(maxd == l ){
                offsetd++ ;
            }else{
                maxd = l;
                offsetd = 1 ;
            }
        }
        String idstr =StrUtil.join(",",ids);
        List<Blog> blogs = query().in("id", ids)
                .last("order by field (id " + idstr + ")")
                .list();
        ScrollResult scrollResult = new ScrollResult();
        for (Blog blog : blogs) {
            // 5.1.查询blog有关的用户
            queryBlogUser(blog);
            // 5.2.查询blog是否被点赞
            isBlogLike(blog);
        }
        ScrollResult r = new ScrollResult();
        r.setList(blogs);
        r.setOffset(offsetd);
        r.setMinTime(maxd);
        return Result.ok(scrollResult);
    }
}
